﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Proggy.Web.Cms.Seo.Service.Abstract;
using System.IO;


namespace Proggy.Web.Cms.Seo.Service.Concrete
{
    /// <summary>
    /// Url optimization service
    /// </summary>
    public class UrlOptimizationService : IUrlOptimizationService
    {
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="addWWW"></param>
        /// <param name="useTrailingSlash"></param>
        public UrlOptimizationService(bool addWWW, bool useTrailingSlash)
        {
            this.AddWWW = addWWW;
            this.UseTrailingSlash = useTrailingSlash;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="requestUri"></param>
        /// <returns></returns>
        public Tuple<bool, Uri> IsOptimizedOkAlready(Uri requestUri)
        {
            // outputs
            string scheme, host, path, query;
            int port = 80;

            // set
            scheme = requestUri.Scheme + "://";
            host = this.GetCorrectHost(requestUri);
            port = requestUri.Port;
            path = this.GetCorrectPath(requestUri);
            query = requestUri.Query;

            // create uri
            var outputUri = new Uri(scheme + host + (port == 80 ? "" : ":" + port) + path + query);

            //
            return new Tuple<bool, Uri>(outputUri.OriginalString == requestUri.OriginalString, outputUri);
        }

        /// <summary>
        /// False if any uppercase letters in path
        /// </summary>
        /// <param name="requestUri"></param>
        /// <returns></returns>
        public bool PathIsLowercase(Uri requestUri)
        {
            // test path
            if (requestUri.AbsolutePath.ToLower() != requestUri.AbsolutePath)
            {
                return false;
            }

            // all ok
            return true;

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="requestUri"></param>
        /// <returns></returns>
        public string GetCorrectHost(Uri requestUri)
        {
            // get array of host
            var hostArray = requestUri.Host.Split('.');

            // check
            if (this.AddWWW && hostArray[0] != null && hostArray[0] != "www")
            {
                return "www." + string.Join(".", hostArray);
            }
            else if (!this.AddWWW && hostArray[0] != null && hostArray[0] == "www")
            {
                return string.Join(".", hostArray.Skip(1));
            }

            // ok
            return requestUri.Host;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="requestUri"></param>
        /// <returns></returns>
        public string GetCorrectPath(Uri requestUri)
        {
            // path
            var path = requestUri.AbsolutePath;

            //
            //var fileInfo = new FileInfo(requestUri.AbsolutePath);
            var hasExtension = Path.HasExtension(requestUri.AbsolutePath);// !string.IsNullOrEmpty(fileInfo.Extension);

            // check lowercase
            if (!this.PathIsLowercase(requestUri))
            {
                path = path.ToLower();
            }

            // check root
            if (!(path.Length == 1 && path == "/"))
            {
                // check slash
                if (this.UseTrailingSlash && path.Substring(path.Length - 1, 1) != "/" && !hasExtension)
                {
                    path = path + "/";
                }
                else if (!this.UseTrailingSlash && path.Substring(path.Length - 1, 1) == "/")
                {
                    path = path.Substring(0, path.Length - 1);
                }
            }

            // return
            return path;
        }

        /// <summary>
        /// 
        /// </summary>
        public bool AddWWW { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public bool UseTrailingSlash { get; set; }
    }
}
